﻿using NAudio.Wave.SampleProviders;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NAudio.Gui;

namespace AudioSourceManager
{
    public class AudioPlayer
    {
        /// <summary>
        /// 异常事件
        /// </summary>
        public Action<string> OnError;

        /// <summary>
        /// 日志事件
        /// </summary>
        public Action<string> OnLog;

        /// <summary>
        /// 音量变化
        /// </summary>
        public Action<float, float> OnAmplitudeChange;

        /// <summary>
        /// 播放停止
        /// </summary>
        public Action OnPlaybackStoped;

        private string _audioFileFullPath;

        public string AudioFileFullPath => _audioFileFullPath;

        private string _waveFormat;

        public string WaveFormatText => _waveFormat;

        private WaveOutEvent _waveOut;

        private SampleChannel _waveIn;

        private IAudioSource _audioSource;

        public string Log => _audioSource == null ? "--" : _audioSource.GetLog();

        private bool isPlaying = false;

        public bool IsPlaying => _waveOut != null && _waveOut.PlaybackState is PlaybackState.Playing;

        public AudioPlayer()
        {
        }

        public void Play(string audioFileFullPath)
        {
            if (string.IsNullOrEmpty(audioFileFullPath))
            {
                OnError?.Invoke("播放路径不可为空");
                return;
            }
            _audioFileFullPath = audioFileFullPath;

            if (_waveIn == null)
            {
                if (!IAudioSource.TryGetAudioPlayer(audioFileFullPath, out _audioSource))
                {
                    OnError?.Invoke("无法初始化播放源");
                    return;
                }
                _audioSource.OnError += OnError;
                _audioSource.StartLog();
                if (_audioSource.TryGetSampleChannel(out SampleChannel sampleChannel))
                {
                    _waveIn = sampleChannel;
                    _waveIn.PreVolumeMeter +=
                        (s, e) => OnAmplitudeChange?.Invoke(e.MaxSampleValues[0], e.MaxSampleValues[1]);
                }
            }

            if (_waveOut == null && _waveIn != null)
            {
                _waveOut = new WaveOutEvent();
                _waveOut.PlaybackStopped += (s, e) => OnPlaybackStoped?.Invoke();
                _waveOut.PlaybackStopped += OnPlaybackStopedCallBack;
                _waveOut.Init(_waveIn,true);
            }

            _waveOut?.Play();
            _waveFormat = $"{_waveOut?.OutputWaveFormat}";

        }

        public void Stop()
        {
            _audioSource.Dispose();
            _audioSource = null;
            _waveOut?.Stop();
            _waveIn = null;
        }

        public void Pause()
        {
            _waveOut?.Pause();
        }

        public void SetVolume(float value)
        {
            if (_waveOut == null) return;
            _waveOut.Volume = 1;
            if (_waveIn == null) return;
            _waveIn.Volume = value;
        }

        private void OnPlaybackStopedCallBack(object sender, StoppedEventArgs e)
        {
            _waveIn = null;
            if (_waveOut != null)
            {
                _waveOut.Dispose();
            }
            _waveOut = null;
        }
    }
}
